tg-me.com/sqlhub/1889
Last Update:
🧠 SQL-задача с подвохом: кто на самом деле опоздал?
У тебя есть таблица с логами входа сотрудников в офис. Но задача не в том, чтобы просто найти "кто пришёл позже 9:00", а выяснить кого стоит считать реально опоздавшим, если учесть такую бизнес-логику:
> Сотрудники входят в офис через турникет. Иногда турникет сканирует пропуск с задержкой, а иногда — несколько сотрудников входят подряд. Поэтому, если кто-то зашёл не позже, чем через 2 минуты после своего коллеги из той же команды — его не считают опоздавшим.
📊 Данные
CREATE TABLE office_logs (
employee_id INT,
team_id INT,
entry_time TIMESTAMP
);
Пример данных:
| employee_id | team_id | entry_time |
|-------------|---------|---------------------|
| 1 | 10 | 2024-01-01 08:59:10 |
| 2 | 10 | 2024-01-01 09:00:50 |
| 3 | 10 | 2024-01-01 09:02:20 |
| 4 | 20 | 2024-01-01 09:03:00 |
| 5 | 20 | 2024-01-01 09:04:40 |
| 6 | 20 | 2024-01-01 09:10:00 |
🎯 Задача
Напиши SQL-запрос, который определяет реально опоздавших сотрудников, если:
1. Время входа позже
09:00:00
2. Они не шли следом за коллегой из своей команды (разница входа больше 2 минут)
3. Один и тот же сотрудник не может быть "оправдан" несколькими — ищем только ближайшего предыдущего по времени из своей команды
💡 Подсказка: тут нужны:
- оконные функции (`LAG`)
- фильтрация по
team_id
- расчёт интервалов времени
- доп. условия на время и порядок
Реальное мышление аналитика начинается там, где бизнес-логика важнее простых фильтров.
✅ Решение:
```sql
WITH logs_with_prev AS (
SELECT
employee_id,
team_id,
entry_time,
LAG(entry_time) OVER (
PARTITION BY team_id
ORDER BY entry_time
) AS prev_entry_time
FROM office_logs
),
marked_late AS (
SELECT
*,
EXTRACT(EPOCH FROM (entry_time - prev_entry_time)) AS seconds_diff
FROM logs_with_prev
)
SELECT
employee_id,
team_id,
entry_time
FROM marked_late
WHERE
entry_time::time > '09:00:00'
AND (
prev_entry_time IS NULL
OR EXTRACT(EPOCH FROM (entry_time - prev_entry_time)) > 120
);
```
🔍 **Что происходит:**
• Сначала `LAG` находит предыдущего входившего из той же команды
• Затем считаем, сколько секунд прошло между входами
• Если прошло больше 2 минут или сотрудник был первым — он **реально опоздал**
📦 Такое решение пригодится, если нужно учитывать **контекст** и **временные связи**, а не просто жёсткие фильтры.
@sqlhub
BY Data Science. SQL hub
Warning: Undefined variable $i in /var/www/tg-me/post.php on line 283
Share with your friend now:
tg-me.com/sqlhub/1889